package seatiger.tomcat.catalina.core;

import seatiger.tomcat.catalina.Constants;
import seatiger.tomcat.catalina.Context;
import seatiger.tomcat.catalina.Wrapper;
import seatiger.tomcat.util.StringManager;

import javax.servlet.*;
import java.io.IOException;

/**
 * RequestDispatcher的标准实现，允许将请求转发到其他资源以创建最终响应，或将另一个资源的输出包含在此资源的响应中
 */
public final class ApplicationDispatcher implements RequestDispatcher {

    private static final StringManager sm =
            StringManager.getManager(Constants.PACKAGE_CORE);

    /**
     * 与此RequestDispatcher关联的Context容器
     */
//    private Context context;

    /**
     * 执行的是forward 还是include
     */
//    private boolean including = false;

    /**
     * 外层请求
     */
//    private ServletRequest outerRequest = null;

    /**
     * 外层响应
     */
//    private ServletResponse outerResponse;

    /**
     * 请求路径中的请求参数
     */
//    private String queryString;

    /**
     * servlet路径
     */
//    private String servletPath;

    /**
     * servlet名称
     */
//    private String name;

    /**
     * 转发关联的Wrapper对象
     */
    private Wrapper wrapper;

    public ApplicationDispatcher(Wrapper wrapper) {
        this.wrapper = wrapper;
        /*this.servletPath = servletPath;
        this.queryString = queryString;
        this.name = name;*/
    }

    @Override
    public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        doForward(request, response);
    }

    @Override
    public void include(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    private void doForward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        if (response.isCommitted()) {
            throw new IllegalStateException
                    (sm.getString("applicationDispatcher.forward.ise"));
        }
        try {
            //清空待发送的buffer数据
            response.resetBuffer();
        } catch (IllegalStateException e) {
            throw e;
        }
        invoke(request, response);
    }

    private void invoke(ServletRequest request, ServletResponse response) throws IOException, ServletException{
        Servlet servlet;
        ServletException servletException = null;
        IOException ioException = null;
        try {
            servlet = wrapper.allocate();
        } catch (ServletException e) {
            servletException = e;
            servlet = null;
        } catch (Throwable e) {
            servletException = new ServletException
                    (sm.getString("applicationDispatcher.allocateException",
                            wrapper.getName()), e);
            servlet = null;
        }
        try {
            servlet.service(request,response);
        } catch (ServletException e) {
            servletException = e;
        } catch (IOException e) {
            ioException = e;
        }
        if (ioException != null){
            throw ioException;
        }
        if (servletException != null){
            throw servletException;
        }
    }

}
